package cn.amossun.starter.event.handler;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.amossun.starter.event.EventDefinition;
import cn.amossun.starter.event.annoation.EventListener;
import cn.amossun.starter.event.annoation.EventBinding;
import cn.amossun.starter.event.annoation.EventPublisher;
import cn.amossun.starter.event.common.Constants;
import cn.amossun.starter.event.property.EventBindingContext;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public interface BindingContextHolder extends EventContextHolder {

    default EventBindingContext process(EventBinding eventBinding, EventDefinition.Scope definition) {
        if(StrUtil.isEmpty(eventBinding.key())){
            return null;
        }
        Map<String, Object> argumentsMap = getArguments(eventBinding.arguments());
        EventBindingContext eventBindingContext = new EventBindingContext(
                String.format(Constants.ROUTING_KEY_TEMPLATE, eventBinding.key(), definition.getCode()),
                eventBinding.exchange() != null ? eventBinding.exchange().name() : null,
                eventBinding.exchange() != null ? eventBinding.exchange().type() : null,
                eventBinding.queue() != null ? eventBinding.queue().name() : null,
                argumentsMap
        );
        return eventBindingContext;
    }

    default String getListenerKey(EventListener eventListener) {
        return StrUtil.isNotEmpty(eventListener.key()) ? eventListener.key() : null;
    }

    default String getRoutingKey(EventListener eventListener){
        String routingKey = getListenerKey(eventListener);
        return String.format(Constants.ROUTING_KEY_TEMPLATE, routingKey, eventListener.definition().getCode());
    }

    default List<String> getListenerKeys(EventListener eventListener) {
        List<EventBindingContext> eventBindingContextList = buildEventBindingsContexts(eventListener, null, null);
        if(CollectionUtil.isNotEmpty(eventBindingContextList)) {
            return eventBindingContextList.stream().map(EventBindingContext::getRoutingKey).collect(Collectors.toList());
        }
        String defaultListenerKey = getRoutingKey(eventListener);
        return Arrays.asList(defaultListenerKey);
    }

    List<EventBindingContext> buildEventBindingsContexts(EventListener eventListener, String defaultListenerKey, String defaultQueueName);

    EventBindingContext buildEventBindingsContext(EventPublisher eventPublisher);

}
